package com.augurit.common.system.service.org.impl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.orm.Page;

import com.augurit.common.constant.OrgConstant;
import com.augurit.common.dao.AcRoleDao;
import com.augurit.common.dao.OmGroupDao;
import com.augurit.common.dao.OmOrgDao;
import com.augurit.common.dao.OmUserGroupDao;
import com.augurit.common.dao.OmUserPositionDao;
import com.augurit.common.entity.OmGroup;
import com.augurit.common.entity.OmOrg;
import com.augurit.common.entity.OmUser;
import com.augurit.common.entity.OmUserGroup;
import com.augurit.common.entity.OmUserPosition;
import com.augurit.common.system.convert.OmGroupConverter;
import com.augurit.common.system.convert.OmUserConverter;
import com.augurit.common.system.service.org.IOmGroupService;
import com.augurit.common.system.service.org.IOmPositionService;
import com.augurit.common.system.util.OrgUtils;
import com.augurit.common.system.web.org.form.OmGroupForm;
import com.augurit.common.system.web.org.form.OmPositionForm;
import com.augurit.common.system.web.org.form.OmUserForm;
import com.augurit.common.util.HqlUtils;
import com.augurit.common.util.PageUtils;
import com.augurit.common.util.lang.CollectionUtils;

/**
 * 工作组逻辑实现类
 */
@Service
@Transactional
public class OmGroupServiceImpl implements IOmGroupService {
	
	// DAO 引用
	@Autowired
	private OmGroupDao omGroupDao;
	
	@Autowired
	private OmUserGroupDao omUserGroupDao;
	
	@Autowired
	private AcRoleDao acRoleDao;
	
	@Autowired
	private OmUserPositionDao omUserPositionDao;
	
	@Autowired
	private OmOrgDao omOrgDao;
	
	@Autowired
	private IOmPositionService omPositionService;

	
	/**
	 * 根据ID获取业务字典项Form对象
	 * @param id 业务字典项主键ID
	 * @return 业务字典项Form对象
	 */
	@Transactional(readOnly = true)
	public OmGroupForm get(Long id){
		if(id != null){
			OmGroup entity = omGroupDao.get(id);
			if(entity != null){
				return OmGroupConverter.convertToForm(entity);
			}
			
		}
		return null;
	}
	
	/**
	 * 根据工作组ID获取工作组名称
	 * @param id 工作组主键
	 * @return 工作组名称
	 */
	@Transactional(readOnly = true)
	public String getGroupName(Long id) {
		return omGroupDao.getGroupName(id);
	}
	
	/**
	 * 根据ID获取业务字典项Form对象
	 * @param id 业务字典项主键ID
	 * @return 业务字典项Form对象
	 */
	@Transactional(readOnly = true)
	public OmGroupForm getForm(Long id){
		if(id != null){
			OmGroup entity = omGroupDao.get(id);
			if(entity != null){
				OmGroupForm form = OmGroupConverter.convertToForm(entity);
				//设置工作组的隶属机构名称
				form.setOrgName(omOrgDao.getOrgName(form.getOrgId()));
				
				//设置工作组的父工作组名称
				if(form.getParentGroupId() != null)
					form.setParentGroupName(omGroupDao.get(form.getParentGroupId()).getGroupName());
				return form;
			}
		}
		return null;
	}
	
	/**
	 * 保存业务字典项Form对象
	 * @param form Form对象
	 */
	public void save(OmGroupForm form){
		omGroupDao.save(form);
	}
	
	/**
	 * 保存业务字典项Form对象数组
	 * @param forms Form对象数组
	 */
	public void save(OmGroupForm[] forms){
		if(forms != null && forms.length > 0){
			for(OmGroupForm form : forms)
				omGroupDao.save(form);
		}
	}

	/**
	 * 根据主键ID删除业务字典项对象
	 * @param id 业务字典项对象主键ID
	 */
	public void delete(Long id) {
		if(id != null)
			omGroupDao.delete(id);
	}
	
	/**
	 * 根据主键ID集合删除多个业务字典项对象
	 * @param ids 业务字典项主键ID集合
	 */
	public void delete(Long[] ids) {
		if(ids != null && ids.length > 0)
			omGroupDao.delete(ids);
	}
	
	/**
	 * 添加工作组
	 * @param form 工作组form对象
	 */
	public void addGroupCascade(OmGroupForm form){
		if(form != null){
			//更新父工作组
			OmGroup parentGroup = null;
			if(form.getParentGroupId() != null){
				parentGroup = omGroupDao.get(form.getParentGroupId());
				omGroupDao.updateGroupAfterAddChildren(parentGroup);
			}
			
			//给工作组需自动赋值的字段赋值
			this.save(form);
			
			String parentSeq = (parentGroup == null?"":parentGroup.getGroupSeq());
			form.setGroupSeq(OrgUtils.calSeqOfObj(form.getGroupId(), form.getParentGroupId(), parentSeq));
			
			form.setSubCount(0);
			form.setIsLeaf(OrgConstant.ZERO);
			form.setGroupLevel(parentGroup == null? 1: parentGroup.getGroupLevel()+1);
			this.save(form);
		}
	}
	
	/**
	 * 删除工作组
	 * @param groupIds 工作组id数组
	 */
	public void deleteGroupCascade(Long...groupIds){
		if(groupIds != null && groupIds.length > 0){
			for(Long groupId:groupIds){
				//获取所有子工作组，不包括自己本身
				List<OmGroupForm> list = omGroupDao.getAllChildren(groupId);
				
				//循环删除关联以及本身
				if(list != null && list.size() > 0){
					for (OmGroupForm form:list) 
						deleteGroupRelateElements(form);
				}
				
				//删除自己
				deleteGroupRelateElements(this.getForm(groupId)); 
			}
		}
	}
	
	/**
	 * 删除工作组所有的关联对象以及本身
	 * @param form 工作组form对象 
	 * */
	private void deleteGroupRelateElements(OmGroupForm form){
		if(form != null){
			Long groupId = form.getGroupId();
			
			//删除工作组下的岗位
			List<Long> posIds = omPositionService.getPositionIdsByGroupId(groupId);
			if(posIds != null && posIds.size() > 0){
				for(Long posId:posIds)
					omPositionService.deletePosition(posId);
			}

			//删除关联的用户
			this.disAssociatedUserFromGroup(groupId);
			
			//删除工作组关联的角色
			acRoleDao.disAssociationRoleFromGroup(groupId);
			
			//删除前修改父工作组的属性
			if(form.getParentGroupId() != null){
				omGroupDao.updateGroupAfterRemoveChildren(form.getParentGroupId());
			}
			
			//删除自己
			omGroupDao.delete(groupId);
		}
	}

	/**
	 * 删除工作组关联的用户
	 * @param groupId 工作组id
	 * */
	public void disAssociatedUserFromGroup(Long groupId){
		if(groupId != null){
			omUserGroupDao.deleteUsersByGroupId(groupId);
		}
	}

	/**
	 * 获取顶级工作组form列表
	 * @return 顶级工作组form列表
	 * */
	@Transactional(readOnly = true)
	public List<OmGroupForm> getTopGroups(){
		return omGroupDao.getTopGroups();
	}
	
	/**
	 * 获取所有的工作组的id
	 * @return 工作组id数组
	 */
	@Transactional(readOnly = true)
	public Long[] getAllGroupIds(){
		return omGroupDao.getAllGroupIds();
	}
	/**
	 * 获取所有的工作组
	 * @return 工作组form对象列表
	 */
	@Transactional(readOnly = true)
	public List<OmGroupForm> getAllGroups(){
		return omGroupDao.getAllGroups();
	}
	
	/**
	 * 获取具有工作组的机构id数组
	 * @return
	 */
	@Transactional(readOnly = true)
	public Long[] getOrgIdsOwnedGroup(){
		return omGroupDao.getOrgIdsOwnedGroup();
	}
	
	/**
	 * 获取一组工作组的直属父机构
	 * @param groupIds 工作组id数组
	 * @return 机构id数组
	 */
	@Transactional(readOnly = true)
	public Long[] getDirectParentOrgIds(Long...groupIds){
		if(groupIds != null && groupIds.length > 0){
			return omGroupDao.getDirectParentOrgIds(groupIds);
		}
		return null;
	}
	
	/**
	 * 获取某一个工作组的直属父工作组，顶级工作组的父工作组为null
	 * @param groupId 工作组id
	 * @return 直属工作组id
	 */
	@Transactional(readOnly = true)
	public Long getDirectParentGroup(Long groupId){
		if(groupId != null){
			OmGroupForm form = this.get(groupId);
			return OrgUtils.getDirectParentObjId(form.getGroupSeq());
		}
		return null;
	}
	
	/**
	 * 获取某一个工作组的间接父工作组，顶级父工作组的间接父工作组为null
	 * @param groupId 工作组id
	 * @return 间接父工作组id列表
	 */
	@Transactional(readOnly = true)
	public List<Long> getIndirectParentGroup(Long groupId){
		List<Long> groupIds = null;
		if(groupIds != null){
			OmGroupForm form = this.get(groupId);
			return OrgUtils.getIndirectParentObjIds(form.getGroupSeq());
		}
		return groupIds;
	}
	
	/**
	 * 获取某一个工作组的所有父工作组（包括直属父工作组和间接父工作组），顶级父工作组的间接父工作组为null
	 * @param groupId 工作组id
	 * @return 所有父工作组id列表
	 */
	@Transactional(readOnly = true)
	public List<Long> getAllParentGroup(Long groupId){
		List<Long> groupIds = null;
		if(groupId != null){
			OmGroupForm form = this.get(groupId);
			return OrgUtils.getAllParentObjIds(form.getGroupSeq());
		}
		
		return groupIds;
	}
	
	/**
	 * 获取某一个用户的所有父工作组（包括直属父工作组和间接父工作组）
	 * @param userId 用户id
	 * @return 所有父工作组id列表
	 */
	@Transactional(readOnly = true)
	public List<Long> getAllParentGroupOfUser(Long userId){
		if(userId != null){
			Set<Long> groupIdSet = new HashSet();
			List<Long> directParentGroupIds =	omUserGroupDao.getGroupIds(userId);
			if(directParentGroupIds != null && directParentGroupIds.size() > 0){
				groupIdSet.addAll(directParentGroupIds);
				
				for(Long groupId: directParentGroupIds){
					List<Long> indirectParentGroupIds = this.getAllParentGroup(groupId);
					if(indirectParentGroupIds != null && indirectParentGroupIds.size() > 0)
						groupIdSet.addAll(indirectParentGroupIds);
				}
				return CollectionUtils.toLongList(groupIdSet);
			}
		}
		return null;
	}
	
	/**
	 * 获取机构下的直属工作组id数组
	 * @param orgId 机构id
	 * @return
	 */
	@Transactional(readOnly = true)
	public Long[] getDirectGroupIdsByOrg(Long orgId){
		if(orgId != null){
			return omGroupDao.getDirectGroupIdsByOrg(orgId);
		}
		return null;
	}
	
	/**
	 * 获取机构的直属工作组
	 * @author 王剑文
	 * @param orgId 机构id
	 * @return
	 */
	@Transactional(readOnly = true)
	public List<OmGroupForm> getDirectGroupsByOrg(Long orgId){
		if(orgId != null){
			return omGroupDao.getDirectGroupsByOrg(orgId);
		}
		return null;
	}
	
	/**
	 * 获取工作组的直属工作组
	 * @author 王剑文
	 * @param groupId 工作组id
	 * @return
	 */
	@Transactional(readOnly = true)
	public List<OmGroupForm> getDirectGroupsByGroup(Long groupId){
		if(groupId != null){
			return omGroupDao.getDirectGroupsByGroup(groupId);
		}
		return null;
	}
	
	/**
	 * 获取工作组下的直属工作组分页对象
	 * @param parentGroupId
	 * @param page
	 * @return
	 */
	@Transactional(readOnly = true)
	public Page<OmGroupForm> getDirectGroupsByGroup(Long parentGroupId, Page<OmGroupForm> page){
		if(parentGroupId != null){
			//建立分页对象
			Page pg = PageUtils.newPageInstance(page);
			
			String hql = "from OmGroup ps where ps.parentGroupId = ?";
			List<Long> values = new ArrayList<Long>();
			values.add(parentGroupId);
			hql += HqlUtils.buildOrderBy(page, "ps");
			pg = omGroupDao.findPage(pg, hql, values);
			List<OmGroupForm> list = OmGroupConverter.convertToFormList(pg.getResult());
			PageUtils.copy(pg, list, page);
			return page;
		}
		
		
		return null;
	}
	
	/**
	 * 获取指定工作组下的岗位
	 * @author 王剑文
	 * @param groupId 工作组id
	 * @return 岗位form列表
	 */
	@Transactional(readOnly = true)
	public List<OmPositionForm> getPositions(Long groupId){
		if(groupId != null){
			return omPositionService.getPositionsByGroupId(groupId);
		}
		return null;
	}
	
	/**
	 * 获取指定工作组下的用户
	 * @author 王剑文
	 * @param groupId 工作组id
	 * @return 用户form列表
	 */
	@Transactional(readOnly = true)
	public List<OmUserForm> getUsers(Long groupId){
		if(groupId != null){
			String hql = "select user from OmUser user, OmUserGroup ps where user.userId=ps.userId and ps.groupId=?";
			List<OmUser> list = omUserGroupDao.find(hql, groupId);
			return OmUserConverter.convertToFormList(list);
		}
		return null;
	}
	/**
	 * 获取指定工作组下没有工作组岗位的用户
	 * @param groupId
	 * @return
	 */
	@Transactional(readOnly = true)
	public List<OmUserForm> getUsersNotHavePos(Long groupId){
		if(groupId != null){
			String hql = "select user from OmUser user, OmUserGroup ps where user.userId=ps.userId and ps.groupId=?";
			List<OmUser> usersInGroup = omUserGroupDao.find(hql, groupId);
			List<Long> usersHavePos = omPositionService.getHavePositionUsers(groupId, OrgConstant.PARTY_TYPE_GROUP);
			this.removeUsersHavePos(usersInGroup, usersHavePos);
			return OmUserConverter.convertToFormList(usersInGroup);
		}
		return null;
	}
	
	/**
	 * 获取工作组下的直属用户id数组
	 * @param groupId 工作组id
	 * @return 用户id数组
	 */
	@Transactional(readOnly = true)
	public Long[] getUserIdsByGroupId(Long groupId){
		return omUserGroupDao.getUserIdsByGroupId(groupId);
	}
	
	/**
	 * 根据工作组id数组获取一批工作组（包括工作组的子工作组）下的所有的用户
	 * @param groupIds 工作组id数组
	 * @return 用户id数组
	 */
	@Transactional(readOnly = true)
	public Long[] getAllUserIdsByGroupIds(Long[] groupIds){
		List<Long> groupIdList = new ArrayList<Long>();
		if (groupIds != null && groupIds.length > 0) {
			for (Long groupId : groupIds) {
				//获取工作组下的所有子机构
				List<Long> childGroupIdList = omGroupDao.getAllChildGroupIds(groupId);
				if (childGroupIdList != null && childGroupIdList.size() > 0)
					groupIdList.addAll(childGroupIdList);
				groupIdList.add(groupId);
			}
		}

		if (groupIdList != null && groupIdList.size() > 0) {
			return omUserGroupDao.getUserIdsByGroupIds(CollectionUtils.toLongArray(groupIdList));
		}
		return null;	
	}
	
	/**
	 * 移除含有工作组岗位的用户
	 * @param userInGroup  工作组中的用户
	 * @param usersHavePos 拥有工作组岗位的用户
	 */
	private void removeUsersHavePos(List<OmUser> userInGroup, List<Long> usersHavePos){
		if(usersHavePos != null && usersHavePos.size() > 0){
			for(Long userId: usersHavePos){
				if(userInGroup != null && userInGroup.size() > 0){
					for(int i = 0; i < userInGroup.size(); i++){
						if(userInGroup.get(i).getUserId().longValue() == userId.longValue()){
							userInGroup.remove(i);
						}
					}
				}
			}
		}
	}
	
	/**
	 * 向工作组中添加用户
	 * @param groupId 工作组id
	 * @param userIds 用户id数组
	 */
	public void addUsersToGroup(Long groupId, Long...userIds){
		if(groupId != null && userIds != null && userIds.length > 0){
			for(Long userId:userIds){
				if(!omUserGroupDao.isUserInGroup(userId, groupId)){
					OmUserGroup userGroup = new OmUserGroup();
					userGroup.setGroupId(groupId);
					userGroup.setUserId(userId);
					omUserGroupDao.save(userGroup);
				}
				
				//更新所在的工作组的父节点
				OmGroup group = omGroupDao.get(groupId);
				omGroupDao.updateGroupAfterAddChildren(group);
			}
		}
	}
	
	/**
	 * 向工作组岗位中添加用户
	 * @param posId 岗位id
	 * @param groupId 工作组id
	 * @param userIds 用户id数组
	 */
	public void addUsersToGroupPos(Long posId, Long groupId, Long...userIds){
		if(groupId != null && userIds != null && userIds.length > 0){
			for(Long userId:userIds){
				
				//判断用户是否已经属于指定工作组的工作组用户
				if(!omUserGroupDao.isUserInGroup(userId, groupId)){
					OmUserGroup userGroup = new OmUserGroup();
					userGroup.setGroupId(groupId);
					userGroup.setUserId(userId);
					omUserGroupDao.save(userGroup);
				}
				
				//判断用户是否已经拥有指定岗位
				if(!omUserPositionDao.isUserHavePos(userId, groupId)){
					OmUserPosition entity = new OmUserPosition();
					entity.setPosId(posId);
					entity.setUserId(userId);
					omUserPositionDao.save(entity);
				}
				
				OmGroup group = omGroupDao.get(groupId);
				omGroupDao.updateGroupAfterAddChildren(group);
			}
		}
	}
	
}
